home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / snippet.exe / GREP.C < prev    next >
C/C++ Source or Header  |  1991-09-30  |  20KB  |  678 lines

  1. /* The  information  in  this  document  is  subject  to  change
  2.  * without  notice  and  should not be construed as a commitment
  3.  * by Digital Equipment Corporation or by DECUS.
  4.  *
  5.  * Neither Digital Equipment Corporation, DECUS, nor the authors
  6.  * assume any responsibility for the use or reliability of  this
  7.  * document or the described software.
  8.  *
  9.  *      Copyright (C) 1980, DECUS
  10.  *
  11.  * General permission to copy or modify, but not for profit,  is
  12.  * hereby  granted,  provided that the above copyright notice is
  13.  * included and reference made to  the  fact  that  reproduction
  14.  * privileges were granted by DECUS.
  15.  */
  16.  
  17. #include <stdio.h>
  18. #include <ctype.h>
  19. #include <dos.h>
  20.  
  21. void file(char *s);
  22. void cant(char *s);
  23. void help(char *hp);
  24. void usage(char *s);
  25. void compile(char *source);
  26. void store(int op);
  27. void badpat(char *message, char *source, char *stop);
  28. void grep(FILE *fp, char *fn);
  29. void error(char *s);
  30.  
  31. /* grep.
  32.  *
  33.  * Runs on the Decus compiler or on vms.
  34.  * Converted for BDS compiler (under CP/M-80), 20-Jan-83, by Chris Kern.
  35.  *
  36.  * Converted to IBM PC with CI-C86 C Compiler June 1983 by David N. Smith
  37.  *
  38.  * Converted to ANSI-style C (Zortech C++) compiler by Bob Jarvis
  39.  *
  40.  * On vms, define as:
  41.  *
  42.  *      grep :== "$disk:[account]grep"          (native)
  43.  *      grep :== "$disk:[account]grep grep"     (Decus)
  44.  *
  45.  * See below for more information.
  46.  */
  47.  
  48.  
  49. char    *documentation =
  50.    "grep searches a file for a given pattern.  Execute by\n"
  51.    "   grep [flags] regular_expression file_list\n"
  52.    "\n"
  53.    "Flags are single characters preceeded by '-':\n"
  54.    "   -c      Only a count of matching lines is printed\n"
  55.    "   -f      Print file name for matching lines switch, see below\n"
  56.    "   -n      Each line is preceeded by its line number\n"
  57.    "   -v      Only print non-matching lines\n"
  58.    "\n"
  59.    "The file_list is a list of files (wildcards are acceptable on RSX modes).\n"
  60.    "\n"
  61.    "The file name is normally printed if there is a file given.\n"
  62.    "The -f flag reverses this action (print name no file, not if more).";
  63.  
  64.  
  65. char    *patdoc =
  66.    "The regular_expression defines the pattern to search for.  Upper- and\n"
  67.    "lower-case are always ignored.  Blank lines never match.  The expression\n"
  68.    "should be quoted to prevent file-name translation.\n"
  69.    "x      An ordinary character (not mentioned below) matches that character.\n"
  70.    "'\\'    The backslash quotes any character.  \"\\$\" matches a dollar-sign.\n"
  71.    "'^'    A circumflex at the beginning of an expression matches the\n"
  72.    "       beginning of a line.\n"
  73.    "'$'    A dollar-sign at the end of an expression matches the end of a line.\n"
  74.    "'.'    A period matches any character except \"new-line\".\n"
  75.    "':a'   A colon matches a class of characters described by the following\n"
  76.    "':d'     character.  \":a\" matches any alphabetic, \":d\" matches digits,\n"
  77.    "':n'     \":n\" matches alphanumerics, \": \" matches spaces, tabs, and\n"
  78.    "': '     other control characters, such as new-line.\n"
  79.    "'*'    An expression followed by an asterisk matches zero or more\n"
  80.    "       occurrances of that expression: \"fo*\" matches \"f\", \"fo\"\n"
  81.    "       \"foo\", etc.\n"
  82.    "'+'    An expression followed by a plus sign matches one or more\n"
  83.    "       occurrances of that expression: \"fo+\" matches \"fo\", etc.\n"
  84.    "'-'    An expression followed by a minus sign optionally matches\n"
  85.    "       the expression.\n"
  86.    "'[]'   A string enclosed in square brackets matches any character in\n"
  87.    "       that string, but no others.  If the first character in the\n"
  88.    "       string is a circumflex, the expression matches any character\n"
  89.    "       except \"new-line\" and the characters in the string.  For\n"
  90.    "       example, \"[xyz]\" matches \"xx\" and \"zyx\", while \"[^xyz]\"\n"
  91.    "       matches \"abc\" but not \"axb\".  A range of characters may be\n"
  92.    "       specified by two characters separated by \"-\".  Note that\n"
  93.    "       [a-z] matches alphabetics, while [z-a] never matches.\n"
  94.    "The concatenation of regular expressions is a regular expression.";
  95.  
  96. #define LMAX    512
  97. #define PMAX    256
  98.  
  99. #define CHAR    1
  100. #define BOL     2
  101. #define EOL     3
  102. #define ANY     4
  103. #define CLASS   5
  104. #define NCLASS  6
  105. #define STAR    7
  106. #define PLUS    8
  107. #define MINUS   9
  108. #define ALPHA   10
  109. #define DIGIT   11
  110. #define NALPHA  12
  111. #define PUNCT   13
  112. #define RANGE   14
  113. #define ENDPAT  15
  114.  
  115. int     cflag;
  116. int     fflag;
  117. int     nflag;
  118. int     vflag;
  119. int     nfile;
  120.  
  121. int     debug   =       0;         /* Set for debug code      */
  122.  
  123. char    *pp;
  124.  
  125. #ifndef vms
  126. char    file_name[81];
  127. #endif
  128.  
  129. char    lbuf[LMAX];
  130. char    pbuf[PMAX];
  131.  
  132. /*******************************************************/
  133.  
  134. int main(int argc, char *argv[])
  135. {
  136.       register char   *p;
  137.       register int    c, i;
  138.       int             gotpattern;
  139.       int             gotcha;
  140.       FILE            *f;
  141.       struct FIND     *sfptr;
  142.  
  143.       if(argc <= 1)
  144.             usage("No arguments");
  145.  
  146.       if(argc == 2 && argv[1][0] == '?' && argv[1][1] == 0)
  147.       {
  148.             help(documentation);
  149.             help(patdoc);
  150.             return;
  151.       }
  152.  
  153.       nfile = argc-1;
  154.       gotpattern = 0;
  155.  
  156.       for(i = 1 ; i < argc ; ++i)
  157.       {
  158.             p = argv[i];
  159.             if(*p == '-')
  160.             {
  161.                   ++p;
  162.                   while((c = *p++) != 0)
  163.                   {
  164.                         switch(tolower(c))
  165.                         {
  166.                         case '?':
  167.                               help(documentation);
  168.                               break;
  169.  
  170.                         case 'C':
  171.                         case 'c':
  172.                               ++cflag;
  173.                               break;
  174.  
  175.                         case 'D':
  176.                         case 'd':
  177.                               ++debug;
  178.                               break;
  179.  
  180.                         case 'F':
  181.                         case 'f':
  182.                               ++fflag;
  183.                               break;
  184.  
  185.                         case 'n':
  186.                         case 'N':
  187.                               ++nflag;
  188.                               break;
  189.  
  190.                         case 'v':
  191.                         case 'V':
  192.                               ++vflag;
  193.                               break;
  194.  
  195.                         default:
  196.                               usage("Unknown flag");
  197.                         }
  198.                   }
  199.                   argv[i] = 0;
  200.                   --nfile;
  201.             } 
  202.             else if(!gotpattern)
  203.             {
  204.                   compile(p);
  205.                   argv[i] = 0;
  206.                   ++gotpattern;
  207.                   --nfile;
  208.             }
  209.       }
  210.  
  211.       if(!gotpattern)
  212.             usage("No pattern");
  213.  
  214.       if(nfile == 0)
  215.             grep(stdin, 0);
  216.       else
  217.       {
  218.             fflag = fflag ^ (nfile > 0);
  219.             for(i = 1 ; i < argc ; ++i)
  220.             {
  221.                   if((p = argv[i]) != NULL)
  222.                   {
  223.                         sfptr = findfirst(p, FA_NORMAL);
  224.  
  225.                         while(sfptr != NULL)
  226.                         {
  227.                               if((f=fopen(sfptr->name, "r")) == NULL)
  228.                                     cant(sfptr->name);
  229.                               else
  230.                               {
  231.                                     grep(f, sfptr->name);
  232.                                     fclose(f);
  233.                               }
  234.  
  235.                               sfptr = findnext();
  236.                         }
  237.                   }
  238.             }
  239.       }
  240. }
  241.  
  242. /*******************************************************/
  243.  
  244. void file(char *s)
  245. {
  246.       printf("File %s:\n", s);
  247. }
  248.  
  249. /*******************************************************/
  250.  
  251. void cant(char *s)
  252. {
  253.       fprintf(stderr, "%s: cannot open\n", s);
  254. }
  255.  
  256.  
  257. /*******************************************************/
  258.  
  259. void help(char *hp)
  260. {
  261.       fputs(hp, stderr);